/*
 * miniFreeRTOS SOC System emulation.
 *
 * Copyright (c) 2024- yanl1229@163.com.
 * Written by yanl1229
 *
 * This code is licensed under the GPL.
 */
#ifndef MM_H
#define MM_H

#include <stdlib.h>
#include <string.h>

/* 堆内存大小 128K */
#define CONFIG_TOTAL_HEAP_SIZE    (128 * 1024)

/**
 * 空闲块链表节点
 */
typedef struct A_BLOCK_LINK
{
    struct A_BLOCK_LINK * pxNextFreeBlock; /* 指向一下个空闲块节点 */
    size_t xBlockSize;                     /* 空闲块的长度 */
}BlockLink_t;

/* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE    (sizeof(BlockLink_t) << 1)

/* Max value that fits in a size_t type. */
#define heapSIZE_MAX              0xFFFFFFFF

/* Check if multiplying a and b will result in overflow. */
#define heapMULTIPLY_WILL_OVERFLOW(a, b)    (((a) > 0) && ((b) > (heapSIZE_MAX /(a))))

/* Check if adding a and b will result in overflow. */
#define heapADD_WILL_OVERFLOW(a, b)         ((a) > (heapSIZE_MAX - (b)))

/*
 * BLOCK_ALLOCED_FLAGS : 只为0x80000000，用来表示内存的空闲状态
 */
#define BLOCK_ALLOCED_FLAGS            (1 << 31)

static inline int set_block_is_alloced(struct A_BLOCK_LINK *block)
{
    return (block->xBlockSize & BLOCK_ALLOCED_FLAGS) != 0;
}

static inline void set_block_alloced(struct A_BLOCK_LINK *block)
{
    block->xBlockSize |= BLOCK_ALLOCED_FLAGS;
}

static inline void set_block_free(struct A_BLOCK_LINK *block)
{
    block->xBlockSize &= ~BLOCK_ALLOCED_FLAGS;
}

#define ALIGNMENT_SIZE        8
#define ALIGNMENT_MASK          0x0007

#define ALIGN_MASK(x, mask)	(((x)+(mask))&~(mask))

extern void mm_init(void);
extern void *kmalloc(size_t size);
extern void *kzalloc(size_t num, size_t size);
extern void kfree(void * pv);

#endif
